package czStvDpds.collisionGeometry;

import czStvDpds.mapmanagment.Map;
import czStvDpds.mapmanagment.Tile;
import czStvDpds.mapmanagment.TilesInfo;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

/**
 * Stará se o převod dlaždic nebo hráčů na hitboxy.
 *
 * @author Jirka
 */
public class HitBoxInitializer {

    private static final double BOX_MINUS_SIZE = 0.03;
    private static HitBoxInitializer hitBoxInitializer;

    public static HitBoxInitializer getHitBoxInitializer() {
        if (hitBoxInitializer == null) {
            hitBoxInitializer = new HitBoxInitializer();
        }
        return hitBoxInitializer;
    }

    public List<SquareHitBox> toSquareHitBox(Tile tile, double x, double y, Map map) {
        List<SquareHitBox> shbes = new LinkedList<>();
        if (tile.isSolid()) {
            if (tile.getId() == 4 || tile.getId() == 5) { // nekorektni reseni druhu dlazdic, predelam
                // Plot, Mříž (tenké)
                // Všeschny "tenké" dlazdice se zatim navzajem napojuji nezavisle na druhu
                // X:
                double newX = x + 0.5;
                double newWidth = 0;

                if (map.getTile((int) (x - 1), (int) y).getId() == 4
                        || map.getTile((int) (x - 1), (int) y).getId() == 5) {
                    newX -= 0.5;
                    newWidth += 0.5;
                }

                if (map.getTile((int) (x + 1), (int) y).getId() == 4
                        || map.getTile((int) (x + 1), (int) y).getId() == 5) {
                    newWidth += 0.5;
                }

                // Finální hitbox pro x
                shbes.add(new SquareHitBox(newX, y + 0.5, newWidth, 0));

                // Y:
                double newY = y + 0.5;
                double newHeight = 0;

                if (map.getTile((int) x, (int) (y - 1)).getId() == 4
                        || map.getTile((int) x, (int) (y - 1)).getId() == 5) {
                    newY -= 0.5;
                    newHeight += 0.5;
                }

                if (map.getTile((int) x, (int) (y + 1)).getId() == 4
                        || map.getTile((int) x, (int) (y + 1)).getId() == 5) {
                    newHeight += 0.5;
                }

                // Finální hitbox pro y
                shbes.add(new SquareHitBox(x + 0.5, newY, 0, newHeight));

                return shbes;

            } else if (tile.getId() == 7 || tile.getId() == 8) { // nekorektni reseni druhu dlazdic, predelam
                // Barel a bedna (nezabírají celou dlaždici
                shbes.add(new SquareHitBox(x + BOX_MINUS_SIZE,
                        y + BOX_MINUS_SIZE,
                        1 - BOX_MINUS_SIZE * 2,
                        1 - BOX_MINUS_SIZE * 2)); // zatim stejne
                return shbes;
            } else {
                // Zbylé dlaždice (plné)
                shbes.add(new SquareHitBox(x, y, 1, 1));
                return shbes;
            }
        } else {
            return null;
        }
    }
    private HashMap<Integer, ArrayList<String>> tileFiles;

    public void loadHitBoxFiles() throws IOException {
        tileFiles = new HashMap<>();
        
        for (int i = 1; i <= TilesInfo.getTilesInfo().getTilesNumber(); i++) {
            if (TilesInfo.getTilesInfo().getTile(i).isSolid()) {
                System.out.println(i);
                BufferedReader reader = new BufferedReader(new FileReader("resources/hitboxes/" + TilesInfo.getTilesInfo().getName(i) + ".txt"));
                ArrayList<String> lines = new ArrayList<>();

                while (true) {
                    String line = reader.readLine();
                    // Když nejsou řádky k načtení
                    if (line == null) {
                        reader.close();
                        break;
                    }

                    // Načíst všechny řádky kromě komentářů
                    if (!line.startsWith("#")) {
                        lines.add(line);
                    }
                }
                
                // Přidat do tileFiles
                tileFiles.put(i, lines);
                
            }
        }
    }

    /**
     * Načte polygonové hitboxy dlaždice z textového souboru podle ID dlaždice.
     *
     * @param tile
     * @param x
     * @param y
     * @param map
     * @return
     */
    public List<PolygonHitBox> getPolygonHitBox(Tile tile, int x, int y, Map map) throws IOException {
        List<PolygonHitBox> phbes = new LinkedList<>();

        if (tile.isSolid()) {
//            System.out.println("NAME: " + TilesInfo.getTilesInfo().getName(tile.getId()));
//            BufferedReader reader = new BufferedReader(new FileReader("resources/hitboxes/" + TilesInfo.getTilesInfo().getName(tile.getId()) + ".txt"));
//            ArrayList<String> lines = new ArrayList<>();
//
//            while (true) {
//                String line = reader.readLine();
//                // Když nejsou řádky k načtení
//                if (line == null) {
//                    reader.close();
//                    break;
//                }
//
//                // Načíst všechny řádky kromě komentářů
//                if (!line.startsWith("#")) {
//                    lines.add(line);
//                }
//            }
//
            // Získat lines
            ArrayList<String> lines = tileFiles.get(tile.getId());
            
            // První řádek určuje druh dlaždice
            String tileType = lines.get(0);
            lines.remove(tileType);
            
            // DEBUG
            ArrayList<String> testLines = tileFiles.get(tile.getId());

            // classic a box
            if (tileType.equals("classic") || tileType.equals("box")) {
                List<PointHitBox> vertices = new LinkedList<>();
                for (String stringVertex : lines) {
                    String[] coordinates = stringVertex.split("~");
                    double vertexX = Double.parseDouble(coordinates[0]);
                    double vertexY = Double.parseDouble(coordinates[1]);

                    vertices.add(new PointHitBox(x + vertexX, y + vertexY));
                }

                // Vytvořit polygon
                PolygonHitBox polygon = new PolygonHitBox();
                for (PointHitBox vertex : vertices) {
                    polygon.add(vertex);
                }

                phbes.add(polygon);
            } else if (tileType.equals("thinWall")) {
                List<PointHitBox> vertices = new LinkedList<>();
                for (String line : lines) {
                    if (line.startsWith("@")) {
                        String[] infos = line.split("-");
                        if (infos[1].equals("center")) {
                            PolygonHitBox phb = new PolygonHitBox();
                            for (PointHitBox vertex : vertices) {
                                phb.add(vertex);
                            }
                            phbes.add(phb);
                        } else if (infos[1].equals("up")
                                && TilesInfo.getTilesInfo().getName(map.getTile(x, y - 1).getId()).equals("fence")
                                && TilesInfo.getTilesInfo().getName(map.getTile(x, y - 1).getId()).equals("bpglass")) {
                            PolygonHitBox phb = new PolygonHitBox();
                            for (PointHitBox vertex : vertices) {
                                phb.add(vertex);
                            }
                            phbes.add(phb);
                        } else if (infos[1].equals("right")
                                && TilesInfo.getTilesInfo().getName(map.getTile(x + 1, y).getId()).equals("fence")
                                && TilesInfo.getTilesInfo().getName(map.getTile(x + 1, y).getId()).equals("bpglass")) {
                            PolygonHitBox phb = new PolygonHitBox();
                            for (PointHitBox vertex : vertices) {
                                phb.add(vertex);
                            }
                            phbes.add(phb);
                        } else if (infos[1].equals("down")
                                && TilesInfo.getTilesInfo().getName(map.getTile(x, y + 1).getId()).equals("fence")
                                && TilesInfo.getTilesInfo().getName(map.getTile(x, y + 1).getId()).equals("bpglass")) {
                            PolygonHitBox phb = new PolygonHitBox();
                            for (PointHitBox vertex : vertices) {
                                phb.add(vertex);
                            }
                            phbes.add(phb);
                        } else if (infos[1].equals("left")
                                && TilesInfo.getTilesInfo().getName(map.getTile(x - 1, y).getId()).equals("fence")
                                && TilesInfo.getTilesInfo().getName(map.getTile(x - 1, y).getId()).equals("bpglass")) {
                            PolygonHitBox phb = new PolygonHitBox();
                            for (PointHitBox vertex : vertices) {
                                phb.add(vertex);
                            }
                            phbes.add(phb);
                        }
                    } else {
                        String[] coordinates = line.split("~");
                        double vertexX = Double.parseDouble(coordinates[0]);
                        double vertexY = Double.parseDouble(coordinates[1]);

                        vertices.add(new PointHitBox(x + vertexX, y + vertexY));
                    }
                }
            }
            
            lines.add(0, tileType);

            // Vrátit phbes
            return phbes;
        }

        // Jinak vrátí false
        return null;
    }
}
